@ -75,7 +75,6 @@ Now we need to add 2 fields to `State`: `instances`, and `instance_buffer`.
```rust
```rust
struct State {
struct State {
instances: Vec<Instance>,
instances: Vec<Instance>,
#[allow(dead_code)]
instance_buffer: wgpu::Buffer,
instance_buffer: wgpu::Buffer,
}
}
```
```
@ -124,45 +123,65 @@ let instance_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor {
&wgpu::util::BufferInitDescriptor {
label: Some("Instance Buffer"),
label: Some("Instance Buffer"),
contents: bytemuck::cast_slice(&instance_data),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::STORAGE,
usage: wgpu::BufferUsage::VERTEX,
}
}
);
);
```
```
We need a way to bind our new instance buffer so we can use it in the vertex shader. We could create a new bind group (and we probably should), but for simplicity, I'm going to add a binding to the `uniform_bind_group` that references our `instance_buffer`.
We're going to need to create a new `VertexBufferDescriptor` for `InstanceRaw`.
```rust
```rust
let uniform_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
The last change we need to make is in the `render()` method. We need to change the range we're using in `draw_indexed()` to include the number of instances.
The last change we need to make is in the `render()` method. We need to bind our `instance_buffer` and we need to change the range we're using in `draw_indexed()` to include the number of instances.
render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as _);
render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as _);
@ -191,37 +212,26 @@ render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as _);
<divclass="warning">
<divclass="warning">
Make sure if you add new instances to the `Vec` that you recreate the `instance_buffer` and as well as `uniform_bind_group`, otherwise your new instances won't show up correctly.
Make sure if you add new instances to the `Vec`, that you recreate the `instance_buffer` and as well as `uniform_bind_group`, otherwise your new instances won't show up correctly.
</div>
</div>
## Storage Buffers
We need to reference our new matrix in `shader.vert` so that we can use it for our instances. Add the following to the top of `shader.vert`.
When we modified `uniform_bind_group_layout`, we specified that our `instance_buffer` would be of type `wgpu::BindingType::StorageBuffer`. A storage buffer functions like an array that persists between shader invocations. Let's take a look at what it looks like in `shader.vert`.
```glsl
```glsl
layout(location=5) in mat4 model_matrix;
layout(location=5) in mat4 model_matrix;
```
```
We declare a storage buffer in a very similar way to how we declare a uniform block. The only real difference is that we use the `buffer` keyword. We can then use `model_matrix` to position our models in the scene. But how do we know what instance to use?
We'll apply the `model_matrix` before we apply `u_view_proj`. We do this because the `u_view_proj` changes the coordinate system from `world space` to `camera space`. Our `model_matrix` is a `world space` transformation, so we don't want to be in `camera space` when using it.
## gl_InstanceIndex
This GLSL variable lets us specify what instance we want to use. We can use the `gl_InstanceIndex` to index our `model_matrix` buffer to get the matrix for the current model.
The value of `gl_InstanceIndex` is based on the range passed to the `instances` parameter of `draw_indexed`. Using `3..instances.len() as _` would mean that the 1st-3rd instances would be skipped.
</div>
With all that done, we should have a forest of trees!
With all that done, we should have a forest of trees!