commit 54f8213cf6fe2f6650294d54ab5697dcc3bf31b1
parent aa6b89c4a2fc1b1bb51d7c182486abe07b22e1c9
Author: Christian Ermann <christianermann@gmail.com>
Date: Sat, 20 Jul 2024 11:22:47 -0400
Unify mesh types
Diffstat:
3 files changed, 55 insertions(+), 93 deletions(-)
diff --git a/src/main.zig b/src/main.zig
@@ -15,7 +15,6 @@ const Mesh = @import("mesh.zig");
const Camera = @import("camera.zig");
const input = @import("input.zig");
-const ClusterMesh = @import("meshlets.zig").ClusterMesh;
const load_obj = @import("load_obj.zig");
@@ -384,12 +383,6 @@ pub const MeshOptions = struct {
data: *const Mesh,
};
-pub const ClusterMeshOptions = struct {
- scale: f32 = 1.0,
- offset: f32x3 = .{ 0, 0, 0 },
- data: *const ClusterMesh,
-};
-
pub const MeshBuffer = struct {
device: *gpu.Device,
queue: *gpu.Queue,
@@ -466,62 +459,17 @@ pub const MeshBuffer = struct {
};
}
- pub fn initMesh(self: *MeshBuffer, options: *const MeshOptions) !*RenderMesh {
- const mesh_data = options.data;
- const num_vertices = mesh_data.positions.len;
- const num_indices = mesh_data.indices.len;
- std.log.info("init mesh with {} vertices, {} indices", .{ num_vertices, num_indices });
-
- const offset_p = try self.positions.allocWrite(mesh_data.positions, self.queue);
- const offset_n = try self.normals.allocWrite(mesh_data.normals, self.queue);
- const offset_t = try self.tex_coords.allocWrite(mesh_data.tex_coords, self.queue);
- _ = try self.tangents.allocWrite(mesh_data.tangents, self.queue);
- _ = try self.bitangents.allocWrite(mesh_data.bitangents, self.queue);
- std.log.info("pnt offsets: {}, {}, {} bytes", .{ offset_p, offset_n, offset_t });
-
- const offset_i = try self.indices.allocWrite(mesh_data.indices, self.queue);
- std.log.info("idx offset: {} bytes", .{offset_i});
-
- const mesh = RenderMesh{
- .num_vertices = num_vertices,
- .num_indices = num_indices,
- .scale = options.scale,
- .offset = options.offset,
- };
-
- const instances = [_]InstanceData{
- mesh.instanceData(),
- };
- const offset_u = try self.instances.allocWrite(&instances, self.queue);
- std.log.info("uniform offset: {} bytes", .{offset_u});
-
- const mesh_id: u32 = @intCast(self.meshes.items.len);
- const indirect_args = [1][5]u32{.{
- @intCast(num_indices),
- 1,
- offset_i / self.indices.attrib_size,
- offset_p / self.positions.attrib_size,
- mesh_id,
- }};
- std.log.info("indirect: {any}", .{indirect_args});
- _ = try self.indirect.allocWrite(&indirect_args, self.queue);
-
- try self.meshes.append(mesh);
- return &self.meshes.items[0];
- }
-
- pub fn initClusterMesh(
+ pub fn initMesh(
self: *MeshBuffer,
- options: *const ClusterMeshOptions,
+ options: *const MeshOptions,
allocator: std.mem.Allocator,
) !*RenderMesh {
const mesh_data = options.data;
const num_vertices = mesh_data.positions.len;
const num_indices = mesh_data.indices.len;
- const num_clusters = mesh_data.descriptors.len;
std.log.info(
- "init mesh with {} vertices, {} indices, {} clusters",
- .{ num_vertices, num_indices, num_clusters },
+ "init mesh with {} vertices, {} indices",
+ .{ num_vertices, num_indices },
);
const offset_p = try self.positions.allocWrite(mesh_data.positions, self.queue);
@@ -544,21 +492,35 @@ pub const MeshBuffer = struct {
};
_ = try self.instances.allocWrite(&instances, self.queue);
- const indirect_args = try allocator.alloc([5]u32, num_clusters);
- defer allocator.free(indirect_args);
-
- var mesh_id: u32 = @intCast(self.meshes.items.len);
- for (mesh_data.descriptors, 0..) |descriptor, i| {
- indirect_args[i] = .{
- @intCast(descriptor.num_triangles * 3),
+ if (mesh_data.descriptors != null) {
+ const descriptors = mesh_data.descriptors.?;
+ const num_clusters = descriptors.len;
+ const indirect_args = try allocator.alloc([5]u32, num_clusters);
+ defer allocator.free(indirect_args);
+
+ var instance_id = self.indirect.count();
+ for (descriptors, 0..) |descriptor, i| {
+ indirect_args[i] = .{
+ @intCast(descriptor.num_triangles * 3),
+ 1,
+ offset_i + descriptor.offset,
+ offset_p,
+ instance_id,
+ };
+ instance_id += 1;
+ }
+ _ = try self.indirect.allocWrite(indirect_args, self.queue);
+ } else {
+ const instance_id = self.indirect.count();
+ const indirect_args = [_][5]u32{.{
+ @intCast(num_indices),
1,
- offset_i + descriptor.offset,
+ offset_i,
offset_p,
- mesh_id,
- };
- mesh_id += 1;
+ instance_id,
+ }};
+ _ = try self.indirect.allocWrite(&indirect_args, self.queue);
}
- _ = try self.indirect.allocWrite(indirect_args, self.queue);
try self.meshes.append(mesh);
return &self.meshes.items[0];
@@ -646,7 +608,7 @@ pub fn main() !void {
var mesh_buffer = MeshBuffer.init(.{
.device = app.device,
.queue = app.queue,
- .n_meshes = 200,
+ .n_meshes = 500,
.n_vertices = 60000,
.n_indices = 60000,
.allocator = allocator,
@@ -657,24 +619,32 @@ pub fn main() !void {
.path = "Cottage_Clean/cottage.obj",
});
- //var bunny_mesh = try load_obj.loadFile(.{
- // .allocator = allocator,
- // .path = "bunny-fixed.obj",
- //});
+ var bunny_mesh = try load_obj.loadFile(.{
+ .allocator = allocator,
+ .path = "teapot.obj",
+ });
const optimizeMesh = @import("forsyth_optimize.zig").optimize;
try optimizeMesh(allocator, &mesh, 32, .{});
+ try optimizeMesh(allocator, &bunny_mesh, 32, .{});
const buildClusters = @import("meshlets.zig").buildClusters;
const cluster_mesh = try buildClusters(allocator, &mesh, 64, 126);
- std.log.info("num clusters: {}", .{cluster_mesh.descriptors.len});
+ const cbunny_mesh = try buildClusters(allocator, &bunny_mesh, 64, 126);
+ std.log.info("num clusters: {}", .{cluster_mesh.descriptors.?.len});
- var render_mesh = try mesh_buffer.initClusterMesh(&.{
+ var render_mesh = try mesh_buffer.initMesh(&.{
.data = &cluster_mesh,
.scale = 1,
.offset = .{ 0, 0, 0 },
}, allocator);
+ _ = try mesh_buffer.initMesh(&.{
+ .data = &cbunny_mesh,
+ .scale = 1,
+ .offset = .{ 0, 0, 0 },
+ }, allocator);
+
var rp = try MeshRenderPipeline.init(&app, &mesh_buffer, &textures, "shaders/mesh_clusters.wgsl");
const material = try Material.init(
diff --git a/src/mesh.zig b/src/mesh.zig
@@ -9,3 +9,10 @@ tex_coords: []f32x3,
tangents: []f32x3,
bitangents: []f32x3,
indices: []u32,
+descriptors: ?[]MeshletDescriptor = null,
+
+pub const MeshletDescriptor = struct {
+ offset: u32,
+ num_vertices: u32,
+ num_triangles: u32,
+};
diff --git a/src/meshlets.zig b/src/meshlets.zig
@@ -2,32 +2,17 @@ const std = @import("std");
const assert = std.debug.assert;
const Mesh = @import("mesh.zig");
+const MeshletDescriptor = Mesh.MeshletDescriptor;
const f32x3 = @Vector(3, f32);
const f32x4 = @Vector(4, f32);
-pub const ClusterDescriptor = struct {
- offset: u32,
- num_vertices: u32,
- num_triangles: u32,
-};
-
-pub const ClusterMesh = struct {
- positions: []f32x4,
- normals: []f32x3,
- tex_coords: []f32x3,
- tangents: []f32x3,
- bitangents: []f32x3,
- indices: []u32,
- descriptors: []ClusterDescriptor,
-};
-
pub fn buildClusters(
allocator: std.mem.Allocator,
mesh: *const Mesh,
max_vertices: u32,
max_triangles: u32,
-) !ClusterMesh {
+) !Mesh {
// Only triangle meshes are supported
assert(mesh.indices.len % 3 == 0);
// Must have at least one triangle
@@ -42,7 +27,7 @@ pub fn buildClusters(
@memset(unused, 1);
const indices = try allocator.alloc(u32, mesh.indices.len);
- var descriptors = std.ArrayList(ClusterDescriptor).init(allocator);
+ var descriptors = std.ArrayList(MeshletDescriptor).init(allocator);
defer descriptors.deinit();
var num_vertices: u32 = 0;