commit 1392f56b6a10e64db00d73e6b24a12f76ed8d57d
parent bbf61fdd93fb8e5a352d58fd7577bc86a52caa54
Author: Christian Ermann <christianermann@gmail.com>
Date: Thu, 11 Jul 2024 17:35:46 -0400
Add ability to update render mesh properties
Diffstat:
3 files changed, 85 insertions(+), 43 deletions(-)
diff --git a/src/load_obj.zig b/src/load_obj.zig
@@ -1,9 +1,7 @@
const std = @import("std");
const gpu = @import("mach_gpu");
-const Mesh = @import("main.zig").Mesh;
-const MeshBuffer = @import("main.zig").MeshBuffer;
-const MeshVertexData = @import("main.zig").MeshVertexData;
+const Mesh = @import("mesh.zig");
const f32x2 = @Vector(2, f32);
const f32x3 = @Vector(3, f32);
@@ -102,10 +100,7 @@ fn parseVertex(line: []const u8) !Vertex {
pub const LoadFileOptions = struct {
allocator: std.mem.Allocator,
- mesh_buffer: *MeshBuffer,
path: []const u8,
- scale: f32 = 1.0,
- offset: f32x3 = .{ 0, 0, 0 },
};
pub fn loadFile(options: LoadFileOptions) !Mesh {
@@ -188,7 +183,7 @@ pub fn loadFile(options: LoadFileOptions) !Mesh {
const nslice = try normals_indexed.toOwnedSlice();
const tslice = try tex_coords_indexed.toOwnedSlice();
const islice = try indices.toOwnedSlice();
- const mesh_data = MeshVertexData{
+ const mesh = Mesh{
.positions = pslice,
.normals = nslice,
.tex_coords = tslice,
@@ -197,24 +192,20 @@ pub fn loadFile(options: LoadFileOptions) !Mesh {
.bitangents = try allocator.alloc(f32x3, pslice.len),
};
- try tangentsAndBitangents(&mesh_data, allocator);
+ try tangentsAndBitangents(&mesh, allocator);
- return options.mesh_buffer.initMesh(&.{
- .scale = options.scale,
- .offset = options.offset,
- .data = &mesh_data,
- });
+ return mesh;
}
fn tangentsAndBitangents(
- mesh_data: *const MeshVertexData,
+ mesh: *const Mesh,
allocator: std.mem.Allocator,
) !void {
- const positions = mesh_data.positions;
- const tex_coords = mesh_data.tex_coords;
- const indices = mesh_data.indices;
- const tangents = mesh_data.tangents;
- const bitangents = mesh_data.bitangents;
+ const positions = mesh.positions;
+ const tex_coords = mesh.tex_coords;
+ const indices = mesh.indices;
+ const tangents = mesh.tangents;
+ const bitangents = mesh.bitangents;
@memset(std.mem.asBytes(tangents), 0);
@memset(std.mem.asBytes(bitangents), 0);
diff --git a/src/main.zig b/src/main.zig
@@ -11,6 +11,7 @@ const SkyBoxRenderPipeline = @import("render_pipeline.zig").SkyBoxRenderPipeline
const CubeMap = @import("cubemap.zig");
const Textures = @import("textures.zig");
const Material = @import("material.zig");
+const Mesh = @import("mesh.zig");
const Camera = @import("camera.zig");
const input = @import("input.zig");
@@ -390,6 +391,15 @@ pub const Buffer = struct {
return offset_start;
}
+ pub fn write(
+ self: *Buffer,
+ data_slice: anytype,
+ queue: *gpu.Queue,
+ offset: u32,
+ ) void {
+ queue.writeBuffer(self.data, offset, data_slice);
+ }
+
pub fn allocWrite(self: *Buffer, data_slice: anytype, queue: *gpu.Queue) !u32 {
const offset = try self.alloc(@intCast(data_slice.len));
queue.writeBuffer(self.data, offset, data_slice);
@@ -406,19 +416,10 @@ pub const MeshBufferOptions = struct {
allocator: std.mem.Allocator,
};
-pub const MeshVertexData = struct {
- positions: []f32x4,
- normals: []f32x3,
- tex_coords: []f32x3,
- tangents: []f32x3,
- bitangents: []f32x3,
- indices: []u32,
-};
-
pub const MeshOptions = struct {
scale: f32 = 1.0,
offset: f32x3 = .{ 0, 0, 0 },
- data: *const MeshVertexData,
+ data: *const Mesh,
};
pub const MeshBuffer = struct {
@@ -435,7 +436,7 @@ pub const MeshBuffer = struct {
instances: Buffer,
indirect: Buffer,
- meshes: std.ArrayList(Mesh),
+ meshes: std.ArrayList(RenderMesh),
pub fn init(options: MeshBufferOptions) MeshBuffer {
const device = options.device;
@@ -453,11 +454,11 @@ pub const MeshBuffer = struct {
.indices = Buffer.init_idx(n_indices, device),
.instances = Buffer.init_instance(options.n_meshes, device),
.indirect = Buffer.init_indirect(options.n_meshes, device),
- .meshes = std.ArrayList(Mesh).init(options.allocator),
+ .meshes = std.ArrayList(RenderMesh).init(options.allocator),
};
}
- pub fn initMesh(self: *MeshBuffer, options: *const MeshOptions) !Mesh {
+ 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;
@@ -473,7 +474,7 @@ pub const MeshBuffer = struct {
const offset_i = try self.indices.allocWrite(mesh_data.indices, self.queue);
std.log.info("idx offset: {} bytes", .{offset_i});
- const mesh = Mesh{
+ const mesh = RenderMesh{
.num_vertices = num_vertices,
.num_indices = num_indices,
.scale = options.scale,
@@ -498,17 +499,36 @@ pub const MeshBuffer = struct {
_ = try self.indirect.allocWrite(&indirect_args, self.queue);
try self.meshes.append(mesh);
- return mesh;
+ return &self.meshes.items[0];
+ }
+
+ pub fn updateMeshes(self: *MeshBuffer) void {
+ std.log.info("RUNNING!", .{});
+ for (self.meshes.items, 0..) |*mesh, i| {
+ if (!mesh.dirty) {
+ std.log.info("{}", .{mesh.dirty});
+ continue;
+ }
+ const offset = @sizeOf(InstanceData) * i;
+ const instances = [_]InstanceData{
+ mesh.instanceData(),
+ };
+ std.log.info("instance: {}", .{mesh.instanceData()});
+ self.instances.write(&instances, self.queue, @intCast(offset));
+ mesh.dirty = false;
+ }
}
};
-pub const Mesh = struct {
+pub const RenderMesh = struct {
num_vertices: usize,
num_indices: usize,
scale: f32 = 1.0,
offset: f32x3 = .{ 0.0, 0.0, 0.0 },
+ material: Material = undefined,
+ dirty: bool = false,
- pub fn instanceData(self: *const Mesh) InstanceData {
+ pub fn instanceData(self: *const RenderMesh) InstanceData {
return InstanceData{
.model_matrix = .{
.{ self.scale, 0, 0, 0 },
@@ -516,9 +536,24 @@ pub const Mesh = struct {
.{ 0, 0, self.scale, 0 },
.{ self.offset[0], self.offset[1], self.offset[2], 1 },
},
- .material = .{ .albedo = 0, .normal = 1, .roughness = 2, .metalness = 3 },
+ .material = self.material,
};
}
+
+ pub fn setScale(self: *RenderMesh, scale: f32) void {
+ self.scale = scale;
+ self.dirty = true;
+ }
+
+ pub fn setOffset(self: *RenderMesh, offset: f32x3) void {
+ self.offset = offset;
+ self.dirty = true;
+ }
+
+ pub fn setMaterial(self: *RenderMesh, material: *const Material) void {
+ self.material = material.*;
+ self.dirty = true;
+ }
};
pub fn main() !void {
@@ -561,24 +596,26 @@ pub fn main() !void {
.allocator = allocator,
});
- _ = try load_obj.loadFile(.{
+ const mesh = try load_obj.loadFile(.{
.allocator = allocator,
- .mesh_buffer = &mesh_buffer,
.path = "Cottage_Clean/cottage.obj",
+ });
+ var render_mesh = try mesh_buffer.initMesh(&.{
+ .data = &mesh,
.scale = 1,
.offset = .{ 0, -5, 15 },
});
+
_ = try load_obj.loadFile(.{
.allocator = allocator,
- .mesh_buffer = &mesh_buffer,
.path = "teapot.obj",
- .scale = 0.05,
- .offset = .{ 0, -0.5, 0 },
+ //.scale = 0.05,
+ //.offset = .{ 0, -0.5, 0 },
});
var rp = try MeshRenderPipeline.init(&app, &mesh_buffer, &textures);
- _ = try Material.init(
+ const material = try Material.init(
&textures,
"Cottage_Clean/Cottage_Clean_Base_Color_fixed.png",
"Cottage_Clean/Cottage_Clean_Normal_fixed.png",
@@ -587,6 +624,9 @@ pub fn main() !void {
app.queue,
);
+ render_mesh.setMaterial(&material);
+ mesh_buffer.updateMeshes();
+
var skybox = SkyBoxRenderPipeline.init(&app, cube_map);
var fp = ForwardScreenPass.init(.{
diff --git a/src/mesh.zig b/src/mesh.zig
@@ -0,0 +1,11 @@
+const std = @import("std");
+
+const f32x3 = @Vector(3, f32);
+const f32x4 = @Vector(4, f32);
+
+positions: []f32x4,
+normals: []f32x3,
+tex_coords: []f32x3,
+tangents: []f32x3,
+bitangents: []f32x3,
+indices: []u32,