@ -112,18 +111,18 @@ You can view a full list of features [here](https://docs.rs/wgpu/0.7.0/wgpu/stru
The `limits` field describes the limit of certain types of resource we can create. We'll use the defaults for this tutorial, so we can support most devices. You can view a list of limits [here](https://docs.rs/wgpu/0.7.0/wgpu/struct.Limits.html).
The `limits` field describes the limit of certain types of resource we can create. We'll use the defaults for this tutorial, so we can support most devices. You can view a list of limits [here](https://docs.rs/wgpu/0.7.0/wgpu/struct.Limits.html).
let swap_chain = device.create_swap_chain(&surface, &sc_desc);
surface.configure(&device, &config);
```
```
Here we are defining and creating the `swap_chain`. The `usage` field describes how the `swap_chain`'s underlying textures will be used. `RENDER_ATTACHMENT` specifies that the textures will be used to write to the screen (we'll talk about more `TextureUsage`s later).
Here we are defining and creating the `swap_chain`. The `usage` field describes how the `swap_chain`'s underlying textures will be used. `RENDER_ATTACHMENT` specifies that the textures will be used to write to the screen (we'll talk about more `TextureUsages`s later).
The `format` defines how the `swap_chain`s textures will be stored on the gpu. Different displays prefer different formats. We use `adapter.get_swap_chain_preferred_format()` to figure out the best format to use.
The `format` defines how the `swap_chain`s textures will be stored on the gpu. Different displays prefer different formats. We use `adapter.get_preferred_format()` to figure out the best format to use.
`width` and `height`, are the width and height in pixels of the swap chain. This should usually be the width and height of the window.
`width` and `height`, are the width and height in pixels of the swap chain. This should usually be the width and height of the window.
@ -136,7 +135,7 @@ At the end of the method, we simply return the resulting struct.
surface,
surface,
device,
device,
queue,
queue,
sc_desc,
config,
swap_chain,
swap_chain,
size,
size,
}
}
@ -159,16 +158,16 @@ You can use heavier libraries like [async_std](https://docs.rs/async_std) and [t
</div>
</div>
## resize()
## resize()
If we want to support resizing in our application, we're going to need to recreate the `swap_chain` everytime the window's size changes. That's the reason we stored the physical `size` and the `sc_desc` used to create the swapchain. With all of these, the resize method is very simple.
If we want to support resizing in our application, we're going to need to recreate the `swap_chain` everytime the window's size changes. That's the reason we stored the physical `size` and the `config` used to create the swapchain. With all of these, the resize method is very simple.
@ -422,7 +421,7 @@ With all that you should have a garishly magenta pentagon in your window.
If you use a color picker on the magenta pentagon, you'll get a hex value of #BC00BC. If you convert this to RGB values you'll get (188, 0, 188). Dividing these values by 255 to get them into the [0, 1] range we get roughly (0.737254902, 0, 0.737254902). This is not the same as we are using for our vertex colors which is (0.5, 0.0, 0.5). The reason for this has to do with color spaces.
If you use a color picker on the magenta pentagon, you'll get a hex value of #BC00BC. If you convert this to RGB values you'll get (188, 0, 188). Dividing these values by 255 to get them into the [0, 1] range we get roughly (0.737254902, 0, 0.737254902). This is not the same as we are using for our vertex colors which is (0.5, 0.0, 0.5). The reason for this has to do with color spaces.
Most monitors use a color space know as sRGB. Our swap chain is (most likely depending on what is returned from `adapter.get_swap_chain_preferred_format()`) using an sRGB texture format. The sRGB format stores colors according to their relative brightness instead of their actual brightness. The reason for this is that our eyes don't perceive light linearly. We notice more differences in darker colors than we do lighter colors.
Most monitors use a color space know as sRGB. Our swap chain is (most likely depending on what is returned from `adapter.get_preferred_format()`) using an sRGB texture format. The sRGB format stores colors according to their relative brightness instead of their actual brightness. The reason for this is that our eyes don't perceive light linearly. We notice more differences in darker colors than we do lighter colors.
You get an approximation of the correct color using the following formula: `srgb_color = (rgb_color / 255) ^ 2.2`. Doing this with an RGB value of (188, 0, 188) will give us (0.511397819, 0.0, 0.511397819). A little off from our (0.5, 0.0, 0.5). While you could tweak the formula to get the desired values, you'll likely save a lot of time by using textures instead as they are stored as sRGB by default, so they don't suffer from the same color inaccuracies that vertex colors do. We'll cover textures in the next lesson.
You get an approximation of the correct color using the following formula: `srgb_color = (rgb_color / 255) ^ 2.2`. Doing this with an RGB value of (188, 0, 188) will give us (0.511397819, 0.0, 0.511397819). A little off from our (0.5, 0.0, 0.5). While you could tweak the formula to get the desired values, you'll likely save a lot of time by using textures instead as they are stored as sRGB by default, so they don't suffer from the same color inaccuracies that vertex colors do. We'll cover textures in the next lesson.
1. We need the DEPTH_FORMAT for when we create the depth stage of the `render_pipeline` and creating the depth texture itself.
1. We need the DEPTH_FORMAT for when we create the depth stage of the `render_pipeline` and creating the depth texture itself.
2. Our depth texture needs to be the same size as our screen if we want things to render correctly. We can use our `sc_desc` to make sure that our depth texture is the same size as our swap chain images.
2. Our depth texture needs to be the same size as our screen if we want things to render correctly. We can use our `config` to make sure that our depth texture is the same size as our swap chain images.
3. Since we are rendering to this texture, we need to add the `RENDER_ATTACHMENT` flag to it.
3. Since we are rendering to this texture, we need to add the `RENDER_ATTACHMENT` flag to it.
4. We technically don't *need* a sampler for a depth texture, but our `Texture` struct requires it, and we need one if we ever want to sample it.
4. We technically don't *need* a sampler for a depth texture, but our `Texture` struct requires it, and we need one if we ever want to sample it.
5. If we do decide to render our depth texture, we need to use `CompareFunction::LessEqual`. This is due to how the `samplerShadow` and `sampler2DShadow()` interacts with the `texture()` function in GLSL.
5. If we do decide to render our depth texture, we need to use `CompareFunction::LessEqual`. This is due to how the `samplerShadow` and `sampler2DShadow()` interacts with the `texture()` function in GLSL.
@ -74,7 +74,7 @@ impl Texture {
We create our `depth_texture` in `State::new()`.
We create our `depth_texture` in `State::new()`.
```rust
```rust
let depth_texture = texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
let depth_texture = texture::Texture::create_depth_texture(&device, &config, "depth_texture");
```
```
We need to modify our `render_pipeline` to allow depth testing.
We need to modify our `render_pipeline` to allow depth testing.
@ -129,13 +129,13 @@ We need to remember to change the `resize()` method to create a new `depth_textu
Make sure you update the `depth_texture`*after* you update `sc_desc`. If you don't, your program will crash as the `depth_texture` will be a different size than the `swap_chain` texture.
Make sure you update the `depth_texture`*after* you update `config`. If you don't, your program will crash as the `depth_texture` will be a different size than the `swap_chain` texture.
The last change we need to make is in the `render()` function. We've created the `depth_texture`, but we're not currently using it. We use it by attaching it to the `depth_stencil_attachment` of a render pass.
The last change we need to make is in the `render()` function. We've created the `depth_texture`, but we're not currently using it. We use it by attaching it to the `depth_stencil_attachment` of a render pass.
@ -27,7 +27,7 @@ The `wgpu_glyph`, and `imgui-wgpu` crates currently depend on `wgpu` 0.7, which
* `CullMode` is no longer a thing, instead `PrimitiveState::cull_mode` will require an `Option<Face>`
* `CullMode` is no longer a thing, instead `PrimitiveState::cull_mode` will require an `Option<Face>`
* Added `clamp_depth` and `conservative` to `PrimitiveState`. Part of this means that `DepthStencilState` no longer has a `clamp_depth` field.
* Added `clamp_depth` and `conservative` to `PrimitiveState`. Part of this means that `DepthStencilState` no longer has a `clamp_depth` field.
* `color_blend` and `alpha_blend` have been moved into the new `blend` field with accepts an `Option<wgpu::BlendState>`
* `color_blend` and `alpha_blend` have been moved into the new `blend` field with accepts an `Option<wgpu::BlendState>`
* `adapter.get_swap_chain_preferred_format()` now returns an `Option<wgpu::TextureFormat>`
* `adapter.get_preferred_format()` now returns an `Option<wgpu::TextureFormat>`
* `wgpu::RenderPassColorAttachmentDescriptor` has been renamed `wgpu::RenderPassColorAttachement` and the `attachment` field has been renamed to `view`
* `wgpu::RenderPassColorAttachmentDescriptor` has been renamed `wgpu::RenderPassColorAttachement` and the `attachment` field has been renamed to `view`
* `wgpu::RenderPassDepthStencialAttachmentDescriptor` also loses the `Descriptor` part of it's name. `attachment` gets renamed to `view` as well.
* `wgpu::RenderPassDepthStencialAttachmentDescriptor` also loses the `Descriptor` part of it's name. `attachment` gets renamed to `view` as well.
* `wgpu::TextureCopyView` has been renamed to `wgpu::ImageCopyTexture`. This is a typedef for `wgpu::ImageCopyTextureBase<T>`
* `wgpu::TextureCopyView` has been renamed to `wgpu::ImageCopyTexture`. This is a typedef for `wgpu::ImageCopyTextureBase<T>`
@ -42,7 +42,7 @@ There were a lot of changes particularly to the `RenderPipelineDescriptor`. Most
School is starting to ramp up, so I haven't had as much time to work on the site as I would like to. Because of that there were some issues piling up. I decided to tackle a bunch of them in one go. Here's a snapshot of what I did:
School is starting to ramp up, so I haven't had as much time to work on the site as I would like to. Because of that there were some issues piling up. I decided to tackle a bunch of them in one go. Here's a snapshot of what I did:
* The tutorial now handles `SwapChainError` properly
* The tutorial now handles `SurfaceError` properly
* I'm now using bytemuck's derive feature on all buffer data structs.
* I'm now using bytemuck's derive feature on all buffer data structs.
* The [instancing tutorial](../beginner/tutorial7-instancing) now uses vertex buffers instead of storage buffers.
* The [instancing tutorial](../beginner/tutorial7-instancing) now uses vertex buffers instead of storage buffers.
* `build.rs` now updates when individual shaders are changed, not whenever `/src` is changed.
* `build.rs` now updates when individual shaders are changed, not whenever `/src` is changed.
@ -88,7 +88,7 @@ Up to this point, we created textures manually everytime. I've pulled out the te
## Fixed panics do to not specifying the correct `usage`
## Fixed panics do to not specifying the correct `usage`
Wgpu has become more strict about what `BufferUsage`s and `TextureUsage`s are required when performing certain operations. For example int the [Wgpu without a window example](/intermediate/windowless/), the `texture_desc` only specified the usage to by `COPY_SRC`. This caused a crash when the `texture` was used as a render target. Adding `OUTPUT_ATTACHMENT` fixed the issue.
Wgpu has become more strict about what `BufferUsage`s and `TextureUsages`s are required when performing certain operations. For example int the [Wgpu without a window example](/intermediate/windowless/), the `texture_desc` only specified the usage to by `COPY_SRC`. This caused a crash when the `texture` was used as a render target. Adding `OUTPUT_ATTACHMENT` fixed the issue.
Now we've talked about not needing to see what the gpu is doing, but we do need to see the results at some point. If we look back to talking about the [swap chain](/beginner/tutorial2-swapchain/#render) we see that we use `swap_chain.get_next_texture()` to grab a texture to draw to. We'll skip that step by creating the texture ourselves. One thing to note here is we need to specify `wgpu::TextureFormat::Rgba8UnormSrgb` to `format` instead of `adapter.get_swap_chain_preferred_format(&surface)` since PNG uses RGBA, not BGRA.
Now we've talked about not needing to see what the gpu is doing, but we do need to see the results at some point. If we look back to talking about the [swap chain](/beginner/tutorial2-swapchain/#render) we see that we use `swap_chain.get_next_texture()` to grab a texture to draw to. We'll skip that step by creating the texture ourselves. One thing to note here is we need to specify `wgpu::TextureFormat::Rgba8UnormSrgb` to `format` instead of `surface.get_preferred_format(&adapter)` since PNG uses RGBA, not BGRA.
```rust
```rust
let texture_size = 256u32;
let texture_size = 256u32;
@ -37,8 +37,8 @@ let texture_desc = wgpu::TextureDescriptor {
sample_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsage::COPY_SRC
usage: wgpu::TextureUsages::COPY_SRC
| wgpu::TextureUsage::RENDER_ATTACHMENT
| wgpu::TextureUsages::RENDER_ATTACHMENT
,
,
label: None,
label: None,
};
};
@ -46,7 +46,7 @@ let texture = device.create_texture(&texture_desc);
let texture_view = texture.create_view(&Default::default());
let texture_view = texture.create_view(&Default::default());
```
```
We're using `TextureUsage::OUTPUT_ATTACHMENT` so wgpu can render to our texture. The `TextureUsage::COPY_SRC` is so we can pull data out of the texture so we can save it to a file.
We're using `TextureUsages::OUTPUT_ATTACHMENT` so wgpu can render to our texture. The `TextureUsages::COPY_SRC` is so we can pull data out of the texture so we can save it to a file.
While we can use this texture to draw our triangle, we need some way to get at the pixels inside it. Back in the [texture tutorial](/beginner/tutorial5-textures/) we used a buffer load color data from a file that we then copied into our buffer. Now we are going to do the reverse: copy data into a buffer from our texture to save into a file. We'll need a buffer big enough for our data.
While we can use this texture to draw our triangle, we need some way to get at the pixels inside it. Back in the [texture tutorial](/beginner/tutorial5-textures/) we used a buffer load color data from a file that we then copied into our buffer. Now we are going to do the reverse: copy data into a buffer from our texture to save into a file. We'll need a buffer big enough for our data.