examples/gkurve: moved vertex uniform data to vertex buffer and added view (#277)

This commit is contained in:
PiergiorgioZagaria 2022-05-15 19:34:09 +02:00 committed by GitHub
parent 34e019a212
commit 2df0bc2786
Failed to generate hash of commit
3 changed files with 42 additions and 32 deletions

View file

@ -2,12 +2,12 @@ struct FragUniform {
type_: u32, type_: u32,
padding: vec3<f32>, padding: vec3<f32>,
} }
@binding(1) @group(0) var<uniform> ubos: array<FragUniform, 3>; @binding(1) @group(0) var<storage> ubos: array<FragUniform>;
@stage(fragment) fn main( @stage(fragment) fn main(
@location(0) uv: vec2<f32>, @location(0) uv: vec2<f32>,
@location(1) bary: vec3<f32>, @location(1) bary: vec3<f32>,
@interpolate(flat) @location(2) instance_index: u32, @interpolate(flat) @location(2) triangle_index: u32,
) -> @location(0) vec4<f32> { ) -> @location(0) vec4<f32> {
// Example 1: Visualize barycentric coordinates: // Example 1: Visualize barycentric coordinates:
// return vec4<f32>(bary.x, bary.y, bary.z, 1.0); // return vec4<f32>(bary.x, bary.y, bary.z, 1.0);
@ -17,10 +17,10 @@ struct FragUniform {
// Example 2: Render gkurves // Example 2: Render gkurves
var inversion = -1.0; var inversion = -1.0;
if(ubos[instance_index].type_ == 1u) { if(ubos[triangle_index].type_ == 1u) {
// Solid triangle // Solid triangle
return vec4<f32>(0.0, 1.0, 0.0, 1.0); return vec4<f32>(0.0, 1.0, 0.0, 1.0);
} else if(ubos[instance_index].type_ == 2u) { } else if(ubos[triangle_index].type_ == 2u) {
// Concave (inverted quadratic bezier curve) // Concave (inverted quadratic bezier curve)
inversion = -1.0; inversion = -1.0;
} else { } else {

View file

@ -14,11 +14,22 @@ pub const Vertex = struct {
uv: @Vector(2, f32), uv: @Vector(2, f32),
}; };
// Simple triangle // Simple triangle
const triangle_half_height = 250*@sqrt(0.75); const WINDOW_WIDTH = 640;
const WINDOW_HEIGHT = 480;
const TRIANGLE_SCALE = 250;
const TRIANGLE_HEIGHT = TRIANGLE_SCALE * @sqrt(0.75);
pub const vertices = [_]Vertex{ pub const vertices = [_]Vertex{
.{ .pos = .{ 0, triangle_half_height, 0, 1 }, .uv = .{ 0.5, 1 } }, .{ .pos = .{ WINDOW_WIDTH / 2 + TRIANGLE_SCALE / 2, WINDOW_HEIGHT / 2 + TRIANGLE_HEIGHT, 0, 1 }, .uv = .{ 0.5, 1 } },
.{ .pos = .{ -250, -triangle_half_height, 0, 1 }, .uv = .{ 0, 0 } }, .{ .pos = .{ WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2, 0, 1 }, .uv = .{ 0, 0 } },
.{ .pos = .{ 250, -triangle_half_height, 0, 1 }, .uv = .{ 1, 0 } }, .{ .pos = .{ WINDOW_WIDTH / 2 + TRIANGLE_SCALE, WINDOW_HEIGHT / 2 + 0, 0, 1 }, .uv = .{ 1, 0 } },
.{ .pos = .{ WINDOW_WIDTH / 2 + TRIANGLE_SCALE / 2, WINDOW_HEIGHT / 2, 0, 1 }, .uv = .{ 0.5, 1 } },
.{ .pos = .{ WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 - TRIANGLE_HEIGHT, 0, 1 }, .uv = .{ 0, 0 } },
.{ .pos = .{ WINDOW_WIDTH / 2 + TRIANGLE_SCALE, WINDOW_HEIGHT / 2 - TRIANGLE_HEIGHT, 0, 1 }, .uv = .{ 1, 0 } },
.{ .pos = .{ WINDOW_WIDTH / 2 - TRIANGLE_SCALE / 2, WINDOW_HEIGHT / 2 + TRIANGLE_HEIGHT, 0, 1 }, .uv = .{ 0.5, 1 } },
.{ .pos = .{ WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2, 0, 1 }, .uv = .{ 0, 0 } },
.{ .pos = .{ WINDOW_WIDTH / 2 - TRIANGLE_SCALE, WINDOW_HEIGHT / 2 + 0, 0, 1 }, .uv = .{ 1, 0 } },
}; };
// TODO: Need to ask Ayush about this, ideally we have a square window in this example because it // TODO: Need to ask Ayush about this, ideally we have a square window in this example because it
@ -40,10 +51,6 @@ const FragUniform = struct {
}; };
// TODO texture and sampler, create buffers and use an index field // TODO texture and sampler, create buffers and use an index field
// in FragUniform to tell which texture to read // in FragUniform to tell which texture to read
// Hard-coded, if you change it remember to change it in the shaders
const num_instances = 3;
const App = @This(); const App = @This();
pipeline: gpu.RenderPipeline, pipeline: gpu.RenderPipeline,
@ -100,7 +107,7 @@ pub fn init(app: *App, engine: *mach.Engine) !void {
}; };
const vbgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); const vbgle = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0);
const fbgle = gpu.BindGroupLayout.Entry.buffer(1, .{ .fragment = true }, .uniform, true, 0); const fbgle = gpu.BindGroupLayout.Entry.buffer(1, .{ .fragment = true }, .read_only_storage, true, 0);
const bgl = engine.gpu_driver.device.createBindGroupLayout( const bgl = engine.gpu_driver.device.createBindGroupLayout(
&gpu.BindGroupLayout.Descriptor{ &gpu.BindGroupLayout.Descriptor{
.entries = &.{ vbgle, fbgle }, .entries = &.{ vbgle, fbgle },
@ -143,16 +150,16 @@ pub fn init(app: *App, engine: *mach.Engine) !void {
const vertex_uniform_buffer = engine.gpu_driver.device.createBuffer(&.{ const vertex_uniform_buffer = engine.gpu_driver.device.createBuffer(&.{
.usage = .{ .copy_dst = true, .uniform = true }, .usage = .{ .copy_dst = true, .uniform = true },
.size = @sizeOf(VertexUniform) * num_instances, .size = @sizeOf(VertexUniform),
.mapped_at_creation = false, .mapped_at_creation = false,
}); });
const frag_uniform_buffer = engine.gpu_driver.device.createBuffer(&.{ const frag_uniform_buffer = engine.gpu_driver.device.createBuffer(&.{
.usage = .{ .uniform = true }, .usage = .{ .storage = true },
.size = @sizeOf(FragUniform) * num_instances, .size = @sizeOf(FragUniform) * vertices.len / 3,
.mapped_at_creation = true, .mapped_at_creation = true,
}); });
var frag_uniform_mapped = frag_uniform_buffer.getMappedRange(FragUniform, 0, num_instances); var frag_uniform_mapped = frag_uniform_buffer.getMappedRange(FragUniform, 0, vertices.len / 3);
const tmp_frag_ubo = [_]FragUniform{ const tmp_frag_ubo = [_]FragUniform{
.{ .{
.type = 1, .type = 1,
@ -171,8 +178,8 @@ pub fn init(app: *App, engine: *mach.Engine) !void {
&gpu.BindGroup.Descriptor{ &gpu.BindGroup.Descriptor{
.layout = bgl, .layout = bgl,
.entries = &.{ .entries = &.{
gpu.BindGroup.Entry.buffer(0, vertex_uniform_buffer, 0, @sizeOf(VertexUniform) * num_instances), gpu.BindGroup.Entry.buffer(0, vertex_uniform_buffer, 0, @sizeOf(VertexUniform)),
gpu.BindGroup.Entry.buffer(1, frag_uniform_buffer, 0, @sizeOf(FragUniform) * num_instances), gpu.BindGroup.Entry.buffer(1, frag_uniform_buffer, 0, @sizeOf(FragUniform) * vertices.len / 3),
}, },
}, },
); );
@ -213,6 +220,13 @@ pub fn update(app: *App, engine: *mach.Engine) !bool {
}; };
{ {
// Using a view allows us to move the camera without having to change the actual
// global poitions of each vertex
const view = zm.lookAtRh(
zm.f32x4(0, 0, 1, 1),
zm.f32x4(0, 0, 0, 1),
zm.f32x4(0, 1, 0, 0),
);
const proj = zm.orthographicRh( const proj = zm.orthographicRh(
@intToFloat(f32, engine.gpu_driver.current_desc.width), @intToFloat(f32, engine.gpu_driver.current_desc.width),
@intToFloat(f32, engine.gpu_driver.current_desc.height), @intToFloat(f32, engine.gpu_driver.current_desc.height),
@ -220,21 +234,18 @@ pub fn update(app: *App, engine: *mach.Engine) !bool {
100, 100,
); );
// TODO: const mvp = zm.mul(zm.mul(view, proj), zm.translation(-1, -1, 0));
// Use better positioning system const ubos = VertexUniform{
const ubos = [_]VertexUniform{ .mat = mvp,
.{ .mat = zm.mul(zm.translation(250, triangle_half_height, 0), proj) },
.{ .mat = zm.mul(zm.translation(-250, 0, 0), proj) },
.{ .mat = zm.mul(zm.translation(250, -triangle_half_height, 0), proj) },
}; };
encoder.writeBuffer(app.vertex_uniform_buffer, 0, VertexUniform, &ubos); encoder.writeBuffer(app.vertex_uniform_buffer, 0, VertexUniform, &.{ubos});
} }
const pass = encoder.beginRenderPass(&render_pass_info); const pass = encoder.beginRenderPass(&render_pass_info);
pass.setPipeline(app.pipeline); pass.setPipeline(app.pipeline);
pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len); pass.setVertexBuffer(0, app.vertex_buffer, 0, @sizeOf(Vertex) * vertices.len);
pass.setBindGroup(0, app.bind_group, &.{ 0, 0 }); pass.setBindGroup(0, app.bind_group, &.{ 0, 0 });
pass.draw(vertices.len, num_instances, 0, 0); pass.draw(vertices.len, 1, 0, 0);
pass.end(); pass.end();
pass.release(); pass.release();

View file

@ -1,29 +1,28 @@
struct VertexUniform { struct VertexUniform {
matrix: mat4x4<f32>, matrix: mat4x4<f32>,
} }
@binding(0) @group(0) var<uniform> ubos: array<VertexUniform, 3>; @binding(0) @group(0) var<uniform> ubo: VertexUniform;
struct VertexOut { struct VertexOut {
@builtin(position) position_clip: vec4<f32>, @builtin(position) position_clip: vec4<f32>,
@location(0) frag_uv: vec2<f32>, @location(0) frag_uv: vec2<f32>,
@location(1) frag_bary: vec3<f32>, @location(1) frag_bary: vec3<f32>,
@interpolate(flat) @location(2) instance_index: u32, @interpolate(flat) @location(2) triangle_index: u32,
} }
@stage(vertex) fn main( @stage(vertex) fn main(
@builtin(instance_index) instanceIdx: u32,
@builtin(vertex_index) vertex_index: u32, @builtin(vertex_index) vertex_index: u32,
@location(0) position: vec4<f32>, @location(0) position: vec4<f32>,
@location(1) uv: vec2<f32>, @location(1) uv: vec2<f32>,
) -> VertexOut { ) -> VertexOut {
var output : VertexOut; var output : VertexOut;
output.position_clip = ubos[instanceIdx].matrix * position; output.position_clip = ubo.matrix * position;
output.frag_uv = uv; output.frag_uv = uv;
output.frag_bary = vec3<f32>( output.frag_bary = vec3<f32>(
f32(vertex_index % 3u == 1u), f32(vertex_index % 3u == 1u),
f32(vertex_index % 3u == 2u), f32(vertex_index % 3u == 2u),
f32(vertex_index % 3u == 0u), f32(vertex_index % 3u == 0u),
); );
output.instance_index = instanceIdx; output.triangle_index = vertex_index / 3u;
return output; return output;
} }