1
0
Fork 0
forked from vv/efemra

starting to fill out entities, materials, textures. cleaned up math a little, still WIP.

This commit is contained in:
Vivianne 2022-07-23 03:00:45 -07:00
parent 78293db515
commit 5887223090
9 changed files with 572 additions and 96 deletions

104
src/math/box.zig Normal file
View file

@ -0,0 +1,104 @@
const std = @import("std");
const Vec4f = @import("vec.zig").Vec4f;
const Mat4f = @import("vec.zig").Mat4f;
const BoxData = packed struct {};
pub fn Box(comptime Vec: type, comptime Shift: comptime_int) type {
return packed struct {
const Self = @This();
pub const empty = Self{
.lo = Vec.s(1 << Shift),
.hi = Vec.s(-(1 << Shift)),
};
lo: Vec,
hi: Vec,
pub inline fn new(lo: Vec, hi: Vec) Self {
return Self{
.lo = lo,
.hi = hi,
};
}
pub inline fn center(self: Self) Vec {
return self.lo.lerpvs(self.hi, 0.5);
}
pub inline fn size(self: Self) Vec {
return self.hi.sub(self.lo);
}
pub inline fn extents(self: Self) Vec {
return self.size().mulvs(0.5);
}
pub inline fn contains(self: Self, pt: Vec) bool {
return pt.gteq(self.lo).all3() and pt.lteq(self.hi).all3();
}
pub inline fn area(self: Self) f32 {
const sz = self.size();
return sz.x * sz.y * if (Vec.nelem > 2) sz.z else 1;
}
pub inline fn fromPts(pts: []const Vec) Self {
var lo = Vec.s(1 << Shift);
var hi = Vec.s(-(1 << Shift));
for (pts) |pt| {
lo = lo.min(pt);
hi = hi.max(pt);
}
return Self{
.lo = lo,
.hi = hi,
};
}
pub inline fn uni(lhs: Self, rhs: Self) Self {
return Self{
.lo = lhs.lo.min(rhs.lo),
.hi = lhs.hi.max(rhs.hi),
};
}
pub inline fn intersect(lhs: Self, rhs: Self) Self {
var lo = lhs.lo.min(rhs.lo);
var hi = lhs.hi.max(rhs.hi);
const mid = lo.lerpvs(hi, 0.5);
const inverted = lo.gt(hi);
lo = lo.select(mid, inverted);
hi = hi.select(mid, inverted);
return Self{
.lo = lo,
.hi = hi,
};
}
// TODO: genericise
pub inline fn transform(matrix: Mat4f, box: Self) Self {
var ct = box.center();
var exts = box.hi.sub(ct);
ct = matrix.mulPt(ct);
exts = matrix.mulExtents(exts);
return Self{
.lo = ct.sub(exts),
.hi = ct.add(exts),
};
}
};
}
// pub const Box2d = Box(Vec2f); // need to understand the shift magic
pub const Box3d = Box(Vec4f, 20);
test "Box3d" {
const b1 = Box3d.fromPts(&.{ Vec4f.s(1), Vec4f.s(-1) });
try std.testing.expectEqual(@as(f32, 8), b1.area());
const v1 = Vec4f.s(0.5);
try std.testing.expect(b1.contains(v1));
}

84
src/math/mat.zig Normal file
View file

@ -0,0 +1,84 @@
const std = @import("std");
const vec = @import("vec.zig");
const Vec3f = vec.Vec3f;
const Vec4f = vec.Vec4f;
pub const Mat3f = Mat(3, Vec3f);
pub const Mat4f = packed struct {
const Self = @This();
pub const zero = Mat(4, Vec4f).zero;
pub const id = Mat(4, Vec4f).id;
pub usingnamespace Mat(4, Vec4f);
pub inline fn lookAt(eye: Vec4f, at: Vec4f, up: Vec4f) Self {
// right-handed (ew)
const f = at.sub(eye).normalize3();
const s = f.cross3(up).normalize3();
const u = s.cross3(f).normalize3();
const tx = -s.dot3(eye);
const ty = -u.dot3(eye);
const tz = f.dot3(eye);
return Self{
.c0 = .{ .x = s.x, .y = u.x, .z = -f.x, .w = 0 },
.c1 = .{ .x = s.y, .y = u.y, .z = -f.y, .w = 0 },
.c2 = .{ .x = s.z, .y = u.z, .z = -f.z, .w = 0 },
.c3 = .{ .x = tx, .y = ty, .z = tz, .w = 1 },
};
}
pub inline fn glPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
const t = std.math.tan(fov_y * 0.5);
var m = zero;
m.c0.x = 1.0 / (aspect * t);
m.c1.y = 1.0 / t;
m.c2.z = -1.0 * (z_far * z_near) / (z_far - z_near);
m.c3.z = -2.0 * (z_far * z_near) / (z_far - z_near);
return m;
}
pub inline fn vkPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
var m = glPerspective(fov_y, aspect, z_near, z_far);
m.c1.y *= -1.0;
return m;
}
};
pub fn Mat(comptime nelem: comptime_int, comptime Vec: type) type {
return packed struct {
const Self = @This();
pub const nelem = nelem;
pub const zero = Self{};
pub const id = Self{
.c0 = .{ .x = 1 },
.c1 = .{ .y = 1 },
.c2 = if (nelem > 2 and Vec.nelem > 2) .{ .z = 1 } else {},
.c3 = if (nelem > 3 and Vec.nelem > 3) .{ .w = 1 } else {},
};
c0: Vec = .{},
c1: Vec = .{},
c2: if (nelem > 2) Vec else void = if (nelem > 2) .{} else {},
c3: if (nelem > 3) Vec else void = if (nelem > 3) .{} else {},
pub inline fn mulCol(self: Self, col: Vec) Vec {
const a = self.c0.mulvs(col.x);
const b = self.c1.mulvs(col.y);
const c = if (nelem > 2 and Vec.nelem > 2) self.c2.mulvs(col.z) else {};
const d = if (nelem > 3 and Vec.nelem > 2) self.c0.mulvs(col.w) else {};
return a.add(b).add(if (nelem > 2) if (nelem > 3) c.add(d) else c else Vec.zero);
}
pub inline fn mul(a: Self, b: Self) Self {
return Self{
.c0 = a.mulCol(b.c0),
.c1 = a.mulCol(b.c1),
.c2 = if (nelem > 2) a.mulCol(b.c2) else {},
.c3 = if (nelem > 3) a.mulCol(b.c3) else {},
};
}
};
}

View file

@ -13,18 +13,65 @@ pub const Vec2u = Vec(2, u32);
pub const Vec3u = Vec(3, u32);
pub const Vec4u = Vec(4, u32);
pub fn Vec(comptime nelem: comptime_int, comptime T: anytype) type {
pub const Vec2b = BoolVec(2);
pub const Vec3b = BoolVec(3);
pub const Vec4b = BoolVec(4);
pub fn BoolVec(comptime nelem: comptime_int) type {
assert(nelem > 1);
assert(nelem <= 4);
return packed struct {
const Self = @This();
x: bool = false,
y: bool = false,
z: if (nelem > 2) bool else void = if (nelem > 2) false else {},
w: if (nelem > 3) bool else void = if (nelem > 3) false else {},
pub inline fn all2(self: Self) bool {
return self.x and self.y;
}
// 3-element operations
pub usingnamespace if (nelem >= 3) struct {
pub inline fn all3(self: Self) bool {
return self.all2() and if (nelem > 2) self.z else true;
}
} else struct {};
pub usingnamespace if (nelem >= 4) struct {
pub inline fn all4(self: Self) bool {
return self.all3() and if (nelem > 3) self.w else true;
}
} else struct {};
};
}
pub fn Vec(comptime nelem: comptime_int, comptime T: type) type {
assert(nelem > 1);
assert(nelem <= 4);
return packed struct {
const Self = @This();
pub const nelem = nelem;
pub const T = T;
const Vecnb = BoolVec(Self.nelem);
x: T = 0,
y: T = 0,
z: if (nelem > 2) T else void = if (nelem > 2) 0 else {},
w: if (nelem > 3) T else void = if (nelem > 3) 0 else {},
pub inline fn s(a: T) Self {
return Self{
.x = a,
.y = a,
.z = if (nelem > 2) a else {},
.w = if (nelem > 3) a else {},
};
}
pub inline fn add(lhs: Self, rhs: Self) Self {
return Self{
.x = lhs.x + rhs.x,
@ -65,6 +112,15 @@ pub fn Vec(comptime nelem: comptime_int, comptime T: anytype) type {
return lhs.mulvs(1 / rhs);
}
pub inline fn min(a: Self, b: Self) Self {
return Self{
.x = @minimum(a.x, b.x),
.y = @minimum(a.y, b.y),
.z = if (nelem > 2) @minimum(a.z, b.z) else {},
.w = if (nelem > 3) @minimum(a.w, b.w) else {},
};
}
pub inline fn max(a: Self, b: Self) Self {
return Self{
.x = @maximum(a.x, b.x),
@ -90,6 +146,24 @@ pub fn Vec(comptime nelem: comptime_int, comptime T: anytype) type {
return self.divvs(self.length());
}
pub inline fn lteq(lhs: Self, rhs: Self) Vecnb {
return Vecnb{
.x = lhs.x <= rhs.x,
.y = lhs.y <= rhs.y,
.z = if (nelem > 2) lhs.z <= rhs.z else {},
.w = if (nelem > 3) lhs.w <= rhs.w else {},
};
}
pub inline fn gteq(lhs: Self, rhs: Self) Vecnb {
return Vecnb{
.x = lhs.x >= rhs.x,
.y = lhs.y >= rhs.y,
.z = if (nelem > 2) lhs.z >= rhs.z else {},
.w = if (nelem > 3) lhs.w >= rhs.w else {},
};
}
// 3-element operations
pub usingnamespace if (nelem >= 3) struct {
pub inline fn sum3(self: Self) T {
@ -158,71 +232,3 @@ test "vec" {
try std.testing.expectEqual(@as(i32, 6), boop.sum());
}
// TODO: comptime magic?
pub const Float4x4 = packed struct {
const Self = @This();
pub const zero = Self{};
pub const id = Self{
.c0 = .{ .x = 1, .y = 0, .z = 0, .w = 0 },
.c1 = .{ .x = 0, .y = 1, .z = 0, .w = 0 },
.c2 = .{ .x = 0, .y = 0, .z = 1, .w = 0 },
.c3 = .{ .x = 0, .y = 0, .z = 0, .w = 1 },
};
c0: Vec4f = .{},
c1: Vec4f = .{},
c2: Vec4f = .{},
c3: Vec4f = .{},
pub inline fn mulCol(self: Self, col: Vec4f) Vec4f {
const a = self.c0.mulvs(col.x);
const b = self.c1.mulvs(col.y);
const c = self.c2.mulvs(col.z);
const d = self.c0.mulvs(col.w);
return a.add(b).add(c.add(d));
}
pub inline fn mul(a: Self, b: Self) Self {
return Self{
.c0 = a.mulCol(b.c0),
.c1 = a.mulCol(b.c1),
.c2 = a.mulCol(b.c2),
.c3 = a.mulCol(b.c3),
};
}
pub inline fn lookAt(eye: Vec4f, at: Vec4f, up: Vec4f) Float4x4 {
// right-handed (ew)
const f = at.sub(eye).normalize3();
const s = f.cross3(up).normalize3();
const u = s.cross3(f).normalize3();
const tx = -s.dot3(eye);
const ty = -u.dot3(eye);
const tz = f.dot3(eye);
return Float4x4{
.c0 = .{ .x = s.x, .y = u.x, .z = -f.x, .w = 0 },
.c1 = .{ .x = s.y, .y = u.y, .z = -f.y, .w = 0 },
.c2 = .{ .x = s.z, .y = u.z, .z = -f.z, .w = 0 },
.c3 = .{ .x = tx, .y = ty, .z = tz, .w = 1 },
};
}
pub inline fn glPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
const t = std.math.tan(fov_y * 0.5);
var m = zero;
m.c0.x = 1.0 / (aspect * t);
m.c1.y = 1.0 / t;
m.c2.z = -1.0 * (z_far * z_near) / (z_far - z_near);
m.c3.z = -2.0 * (z_far * z_near) / (z_far - z_near);
return m;
}
pub inline fn vkPerspective(fov_y: f32, aspect: f32, z_near: f32, z_far: f32) Self {
var m = glPerspective(fov_y, aspect, z_near, z_far);
m.c1.y *= -1.0;
return m;
}
};

View file

@ -1,6 +1,6 @@
const std = @import("std");
const Vec4f = @import("../math/vec.zig").Vec4f;
const Float4x4 = @import("../math/vec.zig").Float4x4;
const Mat4f = @import("../math/mat.zig").Mat4f;
const Quat = @import("../math/quat.zig").Quat;
const Self = @This();
@ -17,16 +17,16 @@ pub fn get() Self {
return s_camera;
}
pub inline fn getProj(self: *const Self, aspect: f32) Float4x4 {
return Float4x4.vkPerspective(std.math.degreesToRadians(f32, self.fov_y), aspect, self.z_near, self.z_far);
pub inline fn getProj(self: *const Self, aspect: f32) Mat4f {
return Mat4f.vkPerspective(std.math.degreesToRadians(f32, self.fov_y), aspect, self.z_near, self.z_far);
}
pub inline fn getView(self: *const Self) Float4x4 {
pub inline fn getView(self: *const Self) Mat4f {
const pos = self.position;
const rot = self.rotation;
return Float4x4.lookAt(pos, pos.add(rot.fwd()), rot.up());
return Mat4f.lookAt(pos, pos.add(rot.fwd()), rot.up());
}
pub inline fn getWorldToClip(self: *const Self, aspect: f32) Float4x4 {
pub inline fn getWorldToClip(self: *const Self, aspect: f32) Mat4f {
return self.getProj(aspect).mul(self.getView());
}

132
src/rendering/Entities.zig Normal file
View file

@ -0,0 +1,132 @@
const std = @import("std");
const assert = std.debug.assert;
const UUID = @import("../common/uuid.zig").UUID;
const mat = @import("../math/mat.zig");
const Mat4f = mat.Mat4f;
const Mat3f = mat.Mat3f;
const vec = @import("../math/vec.zig");
const Vec4f = vec.Vec4f;
const Quat = @import("../math/quat.zig").Quat;
const Box3d = @import("../math/box.zig").Box3d;
const Mesh = @import("meshes.zig").Mesh;
const Material = @import("materials.zig").Material;
// TODO memory
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const Entities = @This();
var s_entities: Entities = undefined;
names: std.ArrayList(UUID),
meshes: std.ArrayList(Mesh.Id),
bounds: std.ArrayList(Box3d),
materials: std.ArrayList(Material),
matrices: std.ArrayList(Mat4f),
inv_matrices: std.ArrayList(Mat3f),
translations: std.ArrayList(Vec4f),
rotations: std.ArrayList(Quat),
scales: std.ArrayList(Vec4f),
mod_time: std.time.Instant,
pub fn init() void {
s_entities.names = std.ArrayList(UUID).init(allocator);
s_entities.meshes = std.ArrayList(Mesh.Id).init(allocator);
s_entities.bounds = std.ArrayList(Box3d).init(allocator);
s_entities.materials = std.ArrayList(Material).init(allocator);
s_entities.matrices = std.ArrayList(Mat4f).init(allocator);
s_entities.inv_matrices = std.ArrayList(Mat3f).init(allocator);
s_entities.translations = std.ArrayList(Vec4f).init(allocator);
s_entities.rotations = std.ArrayList(Quat).init(allocator);
s_entities.scales = std.ArrayList(Vec4f).init(allocator);
s_entities.mod_time = std.time.Instant.now();
}
pub fn update() void {}
pub fn get() *const Entities {
return &s_entities;
}
pub fn deinit() void {
delete(get());
s_entities.names.deinit();
s_entities.meshes.deinit();
s_entities.bounds.deinit();
s_entities.materials.deinit();
s_entities.matrices.deinit();
s_entities.inv_matrices.deinit();
s_entities.translations.deinit();
s_entities.rotations.deinit();
s_entities.scales.deinit();
}
pub fn add(self: *const Entities, name: UUID) !i32 {
self.names.append(name);
self.translations.append(Vec4f.zero);
self.scales.append(Vec4f.one);
self.rotations.append(Quat.id);
self.matrices.append(Mat4f.id);
self.inv_matrices.append(Mat3f.id);
self.mod_time = std.time.Instant.now();
}
pub fn destroyAtIndex(ents: *const Entities, i: i32) void {
assert(i >= 0);
assert(i < ents.names.len);
ents.meshes[i].release();
ents.materials[i].albedo.release();
ents.materials[i].rome.release();
ents.materials[i].normal.release();
}
pub fn removeAtIndex(ents: *const Entities, i: i32) void {
ents.destroyAtIndex(i);
ents.names.swapRemove(i);
ents.meshes.swapRemove(i);
ents.bounds.swapRemove(i);
ents.materials.swapRemove(i);
ents.matrices.swapRemove(i);
ents.inv_matrices.swapRemove(i);
ents.translations.swapRemove(i);
ents.rotations.swapRemove(i);
ents.scales.swapRemove(i);
}
pub fn rm(ents: *const Entities, name: UUID) bool {
if (ents.find(name)) |i| {
ents.removeAtIndex(i);
ents.mod_time = std.time.Instant.now();
return true;
}
return false;
}
pub fn find(ents: *const Entities, name: UUID) ?i32 {
return ents.names.find(name);
}
pub fn clear(ents: *const Entities) void {
for (ents.names) |_, i| {
ents.destroyAtIndex(i);
}
ents.mod_time = std.time.Instant.now();
}
pub fn delete(ents: *const Entities) void {
ents.clear();
ents.names.clearAndFree();
ents.meshes.clearAndFree();
ents.bounds.clearAndFree();
ents.materials.clearAndFree();
ents.matrices.clearAndFree();
ents.inv_matrices.clearAndFree();
ents.translations.clearAndFree();
ents.rotations.clearAndFree();
ents.scales.clearAndFree();
}

View file

@ -0,0 +1,35 @@
const vec = @import("../math/vec.zig");
const Vec4f = vec.Vec4f;
const Texture = @import("textures.zig").Texture;
const DiskTexture = @import("textures.zig").DiskTexture;
pub const MatFlags = packed struct {
emissive: bool = false, // enable emissive term
sky: bool = false, // lookup emission from sky cubemap
water: bool = false,
slime: bool = false,
lava: bool = false,
refractive: bool = false, // enable refraction term
warped: bool = false, // uv animated
animated: bool = false, // keyframe animated
underwater: bool = false, // SURF_UNDERWATER
};
pub const Material = packed struct {
albedo: Texture.Id, // rgba8 srgb (albedo, alpha)
rome: Texture.Id, // rgba8 srgb (roughness, occlusion, metallic, emission)
normal: Texture.Id, // rg16 (tangent space xy)
flags: MatFlags,
mean_free_path: Vec4f, // .w = scatter dir 'g'
ior: f32, // index of refraction
bumpiness: f32,
};
pub const DiskMaterial = packed struct {
albedo: DiskTexture.Id,
rome: DiskTexture.Id,
normal: DiskTexture.Id,
flags: MatFlags,
ior: f32,
};

31
src/rendering/meshes.zig Normal file
View file

@ -0,0 +1,31 @@
const UUID = @import("uuid").UUID;
const vec = @import("../math/vec.zig");
const Vec4f = vec.Vec4f;
const Vec4i = vec.Vec4i;
pub const Mesh = packed struct {
const version = 5;
positions: [*]Vec4f,
normals: [*]Vec4f,
uvs: [*]Vec4f,
tex_indices: [*]Vec4i,
length: i32,
id: Id,
pub const Id = packed struct {
version: u8,
index: u24,
};
};
pub const DiskMesh = packed struct {
version: i32,
length: i32,
name: [64]u8,
pub const Id = packed struct {
id: UUID,
};
};

View file

@ -0,0 +1,74 @@
const vk = @import("vulkan");
const UUID = @import("../common/uuid.zig").UUID;
const Table = @import("../containers/Table.zig");
const Vec2i = @import("../math/vec.zig").Vec2i;
const TTable = Table(Texture.Id);
var s_table: TTable = undefined;
pub fn init() void {
s_table = TTable.init();
}
pub fn update() void {}
pub fn deinit() void {}
pub fn getTable() *const TTable {
return &s_table;
}
pub const Texture = packed struct {
const Self = @This();
const PalRow = enum {
white,
brown,
light_blue,
green,
red,
orange,
gold,
peach,
purple,
magenta,
tan,
light_green,
yellow,
blue,
fire,
brights,
pub const count = @enumToInt(PalRow.brights);
};
size: Vec2i,
texels: [*]u8,
format: vk.Format,
slot: Id,
pub fn get(id: Id) *const Self {
return s_table.get(id);
}
pub fn isCurrent(id: Id) bool {
return s_table.exists(id);
}
pub const Id = packed struct {
version: u8,
index: u24,
};
};
pub const DiskTexture = packed struct {
version: i32,
format: vk.Format,
name: []u8,
size: Vec2i,
pub const Id = packed struct {
id: UUID,
};
};

View file

@ -17,14 +17,17 @@ const framebuffer = @import("framebuffer.zig");
const Targets = @import("Targets.zig");
const RenderPass = @import("RenderPass.zig");
const Bindings = @import("Bindings.zig");
const Entities = @import("../Entities.zig");
const Texture = @import("../textures.zig").Texture;
const vec = @import("../../math/vec.zig");
const mat = @import("../../math/mat.zig");
const Vec2f = vec.Vec2f;
const Vec4f = vec.Vec4f;
const Vec4i = vec.Vec4i;
const Vec2u = vec.Vec2u;
const Vec4u = vec.Vec4u;
const Float4x4 = vec.Float4x4;
const Mat4f = mat.Mat4f;
pub fn init(device: *const Device, swapchain: *Swapchain) !void {
errdefer {
@ -73,7 +76,7 @@ pub fn execute(device: *const Device, swapchain: *Swapchain) !void {
const DepthPass = struct {
const PushConstants = packed struct {
local_to_clip: Float4x4,
local_to_clip: Mat4f,
};
var s_render_pass: vk.RenderPass = undefined;
@ -91,12 +94,6 @@ const DepthPass = struct {
.dst_access_mask = .{ .color_attachment_write_bit = true },
};
//var info = RenderPass.Description{
// .src_stage_mask = .{ .early_fragment_tests_bit = true },
// .src_access_mask = .{ .depth_stencil_attachment_read_bit = true },
// .dst_stage_mask = .{ .late_fragment_tests_bit = true },
// .dst_access_mask = .{ .depth_stencil_attachment_write_bit = true },
//};
info.attachments[0] = .{
.format = depth_buffer.format,
.layout = .depth_stencil_attachment_optimal,
@ -166,7 +163,6 @@ const DepthPass = struct {
defer pm_depth_execute.end();
const camera = Camera.get();
const world_to_clip = camera.getWorldToClip(swapchain.getAspect());
const attachments = &[_]*Image{Targets.getDepthBuffer(swapchain)};
@ -202,7 +198,7 @@ const DepthPass = struct {
const OpaquePass = struct {
const Globals = packed struct {
g_WorldToClip: Float4x4,
g_WorldToClip: Mat4f,
g_Eye: Vec4f,
g_HdrEnabled: f32,
@ -215,8 +211,8 @@ const OpaquePass = struct {
};
const PushConstants = packed struct {
kLocalToWorld: Float4x4,
kIMc0: Vec4f,
kLocalToWorld: Mat4f,
kIMc0: Vec4f, // components of inverse matrix
kIMc1: Vec4f,
kIMc2: Vec4f,
kTexInds: Vec4u,
@ -239,13 +235,6 @@ const OpaquePass = struct {
.dst_access_mask = .{ .color_attachment_write_bit = true },
};
//var info = RenderPass.Description{
// .src_stage_mask = .{ .late_fragment_tests_bit = true },
// .dst_stage_mask = .{ .early_fragment_tests_bit = true, .color_attachment_output_bit = true },
// .src_access_mask = .{ .depth_stencil_attachment_write_bit = true },
// .dst_access_mask = .{ .depth_stencil_attachment_read_bit = true, .color_attachment_write_bit = true },
//};
info.attachments[0] = .{
.format = depth_buffer.format,
.layout = .depth_stencil_attachment_optimal,
@ -436,10 +425,31 @@ const OpaquePass = struct {
cmdbuf.beginRenderPass(device, s_render_pass, fbuf, rect, &clear_values);
defer cmdbuf.endRenderPass(device);
// ITERATE THROUGH ENTITIES AND DRAW THEM FINALLY OMG
const ents = Entities.get();
for (ents.meshes.items) |mesh, i| {
const albedo = Texture.get(ents.materials.items[i].albedo);
const rome = Texture.get(ents.materials.items[i].rome);
const normal = Texture.get(ents.materials.items[i].normal);
const pc = PushConstants{
.kLocalToWorld = ents.matrices[i],
.kIMc0 = ents.invMatrices[i].c0,
.kIMc1 = ents.invMatrices[i].c1,
.kIMc2 = ents.invMatrices[i].c2,
.kTexInds = .{
.x = if (albedo) albedo.slot.index else 0,
.y = if (rome) rome.slot.index else 0,
.z = if (normal) normal.slot.index else 0,
.w = 0,
},
};
cmdbuf.pushConstants(device, &s_pass, &pc);
cmdbuf.drawMesh(mesh.id);
}
const pc = PushConstants{
.kLocalToWorld = Float4x4.id,
.kLocalToWorld = Mat4f.id,
.kIMc0 = Vec4f{ .x = 1, .y = 0, .z = 0, .w = 0 },
.kIMc1 = Vec4f{ .x = 0, .y = 1, .z = 0, .w = 0 },
.kIMc2 = Vec4f{ .x = 0, .y = 0, .z = 1, .w = 0 },