Reputation: 49
I am using wgpu-rs
.
I am drawing a 2D point that's within a triangle. I want this point to have a single color throughout.
My current implementation is repeating some bytes and seems wasteful. I think there must be a better way.
For each (x,y)
pair, it is also including a Vec3<f32>
for color, as (r,g,b)
, a Vec2<f32>
for the center, and an f32
value for the radius. My problem is that this data is repeated for each of the 3 vertices, when I only need it once.
I've written a struct that looks like this to hold the data:
pub struct Point {
pub position: [f32; 2],
pub color: [f32; 3],
pub center: [f32; 2],
pub radius: f32,
}
And the memory layout that goes to build the wgpu::VertexAttribute
s looks like this:
&[
(mem::size_of::<[f32; 2]>(), wgpu::VertexFormat::Float32x2),
(mem::size_of::<[f32; 3]>(), wgpu::VertexFormat::Float32x3),
(mem::size_of::<[f32; 2]>(), wgpu::VertexFormat::Float32x2),
(mem::size_of::<[f32; 1]>(), wgpu::VertexFormat::Float32),
]
(This code is incomplete as is and is only given to clarify my question.)
My question is:
As I am passing the same radius, the same center, and the same color for each vertex, is there a way to bundle the data onto the vertex buffer such that this information is not repeated for each vertex? I cannot use a uniform
here (I would think) because I might be drawing many points of different radii and colors at once, so these variables vary. For every point, the radius, center, and color data is repeated 3 times when I only need it once.
I don't know how to do this as I need the color, center, and radius information for each vertex within the shader module.
I'm not sure if I can, for example, separate the data into distinct structs or use 2 buffers, or something else. It seems there must be some way to reduce the usage of these excess bytes as it would be quite wasteful if many points were drawn.
Upvotes: 0
Views: 150
Reputation: 43782
You can use an index buffer to repeat vertices. An index buffer should contain an array of 16 or 32-bit indices into a vertex buffer, and is specified using set_index_buffer()
. When you draw_indexed()
instead of draw()
, the GPU iterates over the index buffer instead of the vertex buffer, and looks up vertex data from the vertex buffer using each index in the index buffer.
Index buffers are normally used so that each vertex in a complex mesh may be shared by many triangles, but they will also work for your situation; the index buffer would contain
[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, ...]
No other part of your code needs to change to use an index buffer; you just need to create it, set_index_buffer()
it, and call draw_indexed()
instead of draw()
.
It's also possible to leave out the index buffer entirely and do vertex lookups using vertex shader code, but that requires using the vertex buffer differently and I haven't yet used that technique myself.
I think you might be already doing this, but just in case you aren't: a triangle whose vertices all have identical positions as output by the vertex shader will collapse to no pixels. In order to use 3 identical vertices to draw anything, you'll need to have the vertex shader offset the position for each corner of the triangle, using the vertex_index
built-in value modulo 3 to identify which corner of the triangle it's processing.
Upvotes: 1